#include <assert.h>
#include <gfx/idevice.h>
#include <gfx/iprogram.h>
#include <gfx/iprogramparameter.h>
#include <gfx/renderenvironment.h>
#include <gfx/gl20/mesh/morphmesh.h>
#include <math.h>

ceMorphMeshGL20::ceMorphMeshGL20()
  : _mesh(0)
  , _frame0(0)
	, _frame1(0)
{
  CE_OBJECT_CONSTR;
}

ceMorphMeshGL20::~ceMorphMeshGL20()
{
  CE_UNSET(_mesh);
}

void ceMorphMeshGL20::Draw(const ceRenderEnvironment&, iDevice* device)
{
  assert(_mesh);
  device->SetStreamSource(0, _mesh->GetVertices(_frame0));
  device->SetStreamSource(1, _mesh->GetVertices(_frame1));
  device->SetIndices(_mesh->GetIndices());
  device->SetVertexDeclaration(_mesh->GetVertexDeclration());

  iProgram* program = device->GetProgram();
  if (!program)
		{
			return;
		}
  iProgramParameter* pp = program->GetParameter(PPB_Blend);
  if (!pp)
    {
      return;
    }
  pp->Bind (_blend);

  device->DrawIndexPrimitives(PT_Triangles, _mesh->GetIndexDataType(), _mesh->GetNumberOfPrims());
}

void ceMorphMeshGL20::Update(const ceRenderEnvironment&, iDevice*)
{
}

void ceMorphMeshGL20::SetBlend(unsigned frame0, unsigned frame1, float blend)
{

  assert (frame0 < _mesh->GetNumberOfVertexBuffers());
  assert (frame1 < _mesh->GetNumberOfVertexBuffers());
  assert (blend >= 0.0f && blend <= 1.0f);
  _frame0 = frame0;
  _frame1 = frame1;
  _blend = blend;
}

void ceMorphMeshGL20::SetBlend(float blend)
{
  unsigned frame0 = (unsigned)floor(blend);
  unsigned frame1 = (unsigned)ceil(blend);
  blend -= frame0;
  SetBlend(frame0, frame1, blend);
}

void ceMorphMeshGL20::SetMesh (ceMultiMesh* mesh)
{
  CE_SET(_mesh, mesh);
}

const ceMultiMesh* ceMorphMeshGL20::GetMesh () const
{
	return _mesh;
}

ceMultiMesh* ceMorphMeshGL20::GetMesh ()
{
	return _mesh;
}


const ceBoundingBox& ceMorphMeshGL20::GetBoundingBox() const
{
  return _mesh->GetBoundingBox();
}
